<script lang="ts" setup>
  import Pannel from './pannel.vue'
  import DataSelectDialog from './DataSelectDialog.vue'
  import LogicFlow, { ElementState, LogicFlowUtil, Options } from '@logicflow/core'
  import '@logicflow/core/lib/style/index.css'
  import '@logicflow/extension/lib/style/index.css'
  import { Menu } from '@logicflow/extension'
  import { node, customNodeTypes, customEdgeTypes } from '../hook/index'
  import { ElMessage, ElMessageBox } from 'element-plus'
  import { postFetch } from '@/api/common'
  import { LogicFlowData } from '@/types/logicFlow'
  const taskInfo = ref<Partial<categoryCP>>({})
  import router from '@/routers'
  import { categoryCP } from '@/types/categoryCp'
  defineOptions({
    name: 'LogicFlow',
  })
  const route = useRoute()

  const categoryId = route.params.id
  const containerRef = ref<HTMLDivElement | null>(null)
  const lfRef = ref<LogicFlow | null>(null)
  const defaultNode = node()
  const selectNode = ref<any>(null) // 用于存储当前选中的节点
  const selectEdge = ref<any>(null) // 用于存储当前选中的边
  // 右键菜单相关
  const showContextMenu = ref(false)
  const contextMenuX = ref(0)
  const contextMenuY = ref(0)
  const contextMenuNode = ref<any>(null)
  // 数据选择对话框相关
  const showDataDialog = ref(false)
  const currentEditNode = ref<any>(null) // 当前正在编辑的数据节点
  const INIT_DATA = ref<Partial<LogicFlowData>>({}) // 后端返回的流程数据
  // 显示数据选择对话框
  const showDataSelectDialog = (node: any) => {
    currentEditNode.value = node
    showDataDialog.value = true
  }

  // 处理数据选择确认
  const handleDataSelectConfirm = (data: { auditTime: any; userId: string[] }) => {
    if (currentEditNode.value && lfRef.value) {
      lfRef.value.setProperties(currentEditNode.value.id, {
        ...currentEditNode.value.properties,
        auditTime: data.auditTime,
        userId: data.userId,
      })
      console.log('设置数据后的节点属性:', currentEditNode.value)
      ElMessage.success('数据设置成功')
    }
  }

  // 显示名称修改对话框
  const showNameDialog = (node: any) => {
    const currentName = node.text?.value || node.text || '自定义节点'
    ElMessageBox.prompt('请输入节点名称:', '修改名称', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      inputValue: currentName,
    })
      .then(({ value }) => {
        if (value && value.trim()) {
          lfRef.value?.changeNodeText(node.id, value.trim())
          ElMessage.success('名称修改成功')
        }
      })
      .catch(() => {
        // 用户取消
      })
  }
  // 显示颜色选择对话框
  const showColorDialog = (node: any) => {
    const colors = [
      { name: '蓝色', value: '#229DEA' },
      { name: '绿色', value: '#22EA29' },
      { name: '橙色', value: '#EA8622' },
      { name: '红色', value: '#EA2222' },
      { name: '紫色', value: '#8622EA' },
      { name: '粉色', value: '#EA22B4' },
    ]

    let colorOptions = '请选择颜色:\n'
    colors.forEach((color, index) => {
      colorOptions += `${index + 1}. ${color.name}\n`
    })

    ElMessageBox.prompt(colorOptions, '设置颜色', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      inputValue: '1',
      inputPattern: /^[1-6]$/,
      inputErrorMessage: '请输入1-6之间的数字',
    })
      .then(({ value }) => {
        const colorIndex = parseInt(value) - 1
        if (colorIndex >= 0 && colorIndex < colors.length) {
          lfRef.value?.setProperties(node.id, {
            ...node.properties,
            borderColor: colors[colorIndex].value,
          })
          ElMessage.success('颜色设置成功')
        }
      })
      .catch(() => {
        // 用户取消
      })
  }

  const handleBack = () => {
    // 这里可以实现返回上一级或历史记录功能
    ElMessage.info('返回功能')
  }

  // 右键菜单处理函数
  const handleMenuSetData = (node: any) => {
    showDataSelectDialog(node)
    showContextMenu.value = false
  }

  const handleMenuEditName = (node: any) => {
    showNameDialog(node)
    showContextMenu.value = false
  }

  const handleMenuSetColor = (node: any) => {
    showColorDialog(node)
    showContextMenu.value = false
  }

  const handleMenuDeleteNode = (node: any) => {
    lfRef.value?.deleteNode(node.id)
    showContextMenu.value = false
  }

  // 拖放功能处理函数
  const handleDragOver = (event: DragEvent) => {
    event.preventDefault() // 允许拖放
    event.dataTransfer!.dropEffect = 'copy'
  }
  // 处理左侧拖拽到画布上
  const handleDrop = (event: DragEvent) => {
    event.preventDefault()
    try {
      const dragData = JSON.parse(event.dataTransfer?.getData('application/json') || '{}')
      if (!dragData.type || !lfRef.value) {
        return
      }
      console.log('拖拽的节点属性', dragData)
      // 获取画布容器的位置信息
      const containerRect = containerRef.value?.getBoundingClientRect()
      if (!containerRect) return
      // 计算相对于容器的坐标
      const containerX = event.clientX - containerRect.left
      const containerY = event.clientY - containerRect.top
      // 使用 LogicFlow 的坐标转换方法
      const canvasPosition = lfRef.value.getPointByClient({ x: event.clientX, y: event.clientY })
      // 生成唯一的节点ID
      const nodeId = new Date().getTime().toString()
      // 创建新节点，使用 canvasPosition 的正确属性
      const newNode = {
        id: nodeId,
        type: dragData.type,
        x: canvasPosition.canvasOverlayPosition.x,
        y: canvasPosition.canvasOverlayPosition.y,
        text: dragData.text,
        properties: dragData.properties || {},
      }
      // 添加节点到画布
      lfRef.value.addNode(newNode)
      ElMessage.success(`已添加节点: ${dragData.text}`)
    } catch (error) {
      console.error('拖放处理错误:', error)
      ElMessage.error('添加节点失败')
    }
  }
  // 是否增加守卫函数，支持两个函数 beforeClone、beforeDelete，函数返回 true 则执行默认逻辑，返回 false 则阻止。
  const guards: Options.GuardsConfig = {
    beforeDelete(data) {
      // 禁止删除起始节点
      if (['10000', '20000'].includes(data.id)) {
        ElMessage.warning('起始节点和结束节点不允许删除！')
        return false
      } else {
        return true
      }
    },
  }
  /** 初始化事件监听处理器 */
  const initEventHandlers = () => {
    if (!lfRef.value) {
      console.warn('LogicFlow实例未初始化，无法注册事件')
      return
    }
    // 自定义右键菜单处理
    lfRef.value.on('node:contextmenu', ({ data, e }) => {
      console.log('右键点击节点:', data.id, data.type)
      // 如果是开始节点或结束节点，不显示菜单
      if (['10000', '20000'].includes(data.id)) {
        console.log('开始/结束节点，不显示菜单')
        e.preventDefault()
        return
      }
      // 阻止默认右键菜单
      e.preventDefault()
      // 显示自定义菜单
      contextMenuNode.value = data
      contextMenuX.value = e.clientX
      contextMenuY.value = e.clientY
      showContextMenu.value = true

      console.log('显示自定义菜单')
    })

    // 点击其他地方隐藏菜单
    document.addEventListener('click', () => {
      showContextMenu.value = false
    })
    // 禁用自定义Vue节点的文本编辑功能
    lfRef.value.on('text:dbclick', ({ data }) => {
      // 如果是自定义Vue节点，阻止文本编辑
      if (data.type === 'custom-vue-node') {
        return false // 阻止默认的文本编辑行为
      }
    })
    // 节点双击事件 - 对于自定义Vue节点，不触发文本编辑
    lfRef.value.on('node:dbclick', ({ data }) => {
      if (data.type === 'custom-vue-node') {
        // 自定义Vue节点双击不触发文本编辑，而是触发右键菜单中的设置
        console.log('自定义Vue节点双击 - 禁用文本编辑')
        return false
      }
    })
    // 节点点击
    lfRef.value.on('node:click', ({ data }) => {
      selectNode.value = data
      if (lfRef.value) {
        const model = lfRef.value.graphModel.getElement(data.id)
        if (model) {
          model.setProperties({ fill: 'red' })
        }
      }
      data.fill = 'red'
      console.log('选中的节点:', data)
    })
    // 边点击
    lfRef.value.on('edge:click', ({ data }) => {
      selectEdge.value = data
      console.log('选中的边:', data)
    })
    // 节点删除
    lfRef.value.on('node:delete', ({ data }) => {
      const nodeText = data.text?.value || data.text || '节点'
      ElMessage.success(`已删除节点 ${nodeText}！`)
      selectNode.value = null // 清除选中状态
    })
    lfRef.value.on('edge:add', ({ data }) => {
      // 如果边的类型不是我们的自定义类型，则更新它
      if (data.type !== 'EDGE_BEZIER' && lfRef.value) {
        console.log('触发了自动更新边类型:', data)
        lfRef.value.changeEdgeType(data.id, 'EDGE_BEZIER')
      }
    })
  }

  //====================     各种事件处理BEGIN      =====================
  // 工具栏操作函数
  const handleZoomIn = () => {
    if (lfRef.value) {
      lfRef.value.zoom(true)
    }
  }
  const handleZoomOut = () => {
    if (lfRef.value) {
      lfRef.value.zoom(false)
    }
  }
  const handleFitView = () => {
    if (lfRef.value) {
      lfRef.value.fitView()
    }
  }
  const handleSave = async () => {
    if (lfRef.value) {
      const data = lfRef.value.getGraphData()
      await postFetch('/logicFlow/update', { id: INIT_DATA.value.id, data: JSON.stringify(data) })
      ElMessage.success('流程保存成功！')
    }
  }
  const handleClear = () => {
    if (lfRef.value) {
      lfRef.value.clearData()
      ElMessage.success('画布已清空！')
    }
  }
  const handleDeleteNode = () => {
    if (selectNode.value) {
      const nodeText = selectNode.value.text?.value || selectNode.value.text || '节点'
      ElMessageBox.confirm(`确定要删除节点 ${nodeText} 吗？`)
        .then(() => {
          lfRef.value?.deleteNode(selectNode.value.id)
          selectNode.value = null // 清除选中状态
        })
        .catch(() => {
          console.log('删除操作已取消')
        })
    }
  }
  const handleDeleteEdge = () => {
    if (lfRef.value) {
      const selectedEdges = lfRef.value.getSelectElements()
      if (selectedEdges.edges && selectedEdges.edges.length > 0) {
        selectedEdges.edges.forEach((edge) => {
          lfRef.value!.deleteEdge(edge.id)
        })
        ElMessage.success(`已删除 ${selectedEdges.edges.length} 条连线！`)
      } else {
        ElMessage.warning('请先选择要删除的连线！')
      }
    }
  }

  // =======================  END   ============================

  /** 初始化LogicFlow */
  const initLogicFlow = () => {
    if (containerRef.value) {
      lfRef.value = new LogicFlow({
        container: containerRef.value,
        keyboard: {
          enabled: true,
        },
        grid: true,
        guards: guards,
        // 设置默认边类型
        edgeType: 'EDGE_BEZIER',
        // 禁用文本编辑功能
        textEdit: false,
        // 禁用文本双击编辑
        allowTextEdit: false,
      })
      // 注册自定义节点类型
      Object.entries(customNodeTypes).forEach(([type, nodeConfig]) => {
        lfRef.value.register(type, () => nodeConfig)
      })
      // 注册自定义边类型
      Object.entries(customEdgeTypes).forEach(([type, edgeConfig]) => {
        lfRef.value.register(type, () => edgeConfig)
      })

      lfRef.value.render(INIT_DATA.value.data || defaultNode)
      // 扩展
      initEventHandlers() // 初始化事件处理器
    }
  }
  // 修复可访问性问题：为有焦点的元素移除 aria-hidden
  const handleFocus = () => {
    const focusedElements = document.querySelectorAll('[aria-hidden="true"]:focus-within, [aria-hidden="true"]:focus')
    focusedElements.forEach((element) => {
      element.removeAttribute('aria-hidden')
    })
  }

  // 添加 Ctrl+S 快捷键保存
  const handleKeyDown = (e: KeyboardEvent) => {
    if (e.ctrlKey && e.key === 's') {
      e.preventDefault()
      handleSave()
    }
  }

  // 组件卸载时的清理工作
  onUnmounted(() => {
    document.removeEventListener('focusin', handleFocus)
    document.removeEventListener('keydown', handleKeyDown)
    // 销毁 LogicFlow 实例
    if (lfRef.value) {
      lfRef.value.destroy()
      lfRef.value = null
    }
  })

  onMounted(async () => {
    // 获取流程数据
    if (categoryId === null || categoryId === '') {
      ElMessage.error('流程分类ID不能为空！')
      router.go(-1)
      return
    }
    const res = await postFetch('/logicFlow/get', { id: categoryId })
    taskInfo.value = await postFetch('/competition/category/detail', { id: categoryId })
    INIT_DATA.value = res || {}
    // 安全地解析 data 字段
    if (typeof INIT_DATA.value.data === 'string') {
      INIT_DATA.value.data = JSON.parse(INIT_DATA.value.data || '{}')
    } else if (!INIT_DATA.value.data) {
      INIT_DATA.value.data = {}
    }
    // 确保 DOM 完全挂载后再初始化
    nextTick(() => {
      initLogicFlow()
    })
    // 监听焦点事件
    document.addEventListener('focusin', handleFocus)
    // 监听键盘事件
    document.addEventListener('keydown', handleKeyDown)
  })
</script>

<template>
  <div class="app-container">
    <el-row type="flex" justify="space-around" class="main-row">
      <el-col :span="3" class="panel-col">
        <Pannel />
      </el-col>
      <el-col :span="20" class="content-col">
        <div class="topbar">
          <div class="tip">
            <span>流程创建时间：{{ INIT_DATA.createTime }}</span>
            <span>流程更新时间：{{ INIT_DATA.updateTime }}</span>
          </div>
          <div class="toolbar">
            <el-tooltip content="放大" placement="top">
              <el-button type="primary" circle icon="ZoomIn" size="small" @click="handleZoomIn" />
            </el-tooltip>
            <el-tooltip content="缩小" placement="top">
              <el-button type="primary" circle icon="ZoomOut" size="small" @click="handleZoomOut" />
            </el-tooltip>
            <el-tooltip content="适应画布" placement="top">
              <el-button type="primary" circle icon="FullScreen" size="small" @click="handleFitView" />
            </el-tooltip>
            <el-tooltip content="保存流程" placement="top">
              <el-button type="success" circle icon="Check" size="small" @click="handleSave" />
            </el-tooltip>
            <!-- <el-tooltip content="清空画布" placement="top">
            <el-button type="warning" circle icon="Delete" size="small" @click="handleClear" />
          </el-tooltip> -->
            <el-tooltip content="删除选中节点" placement="top">
              <el-button type="danger" circle icon="Close" size="small" :disabled="!selectNode" @click="handleDeleteNode" />
            </el-tooltip>
            <el-tooltip content="删除选中连线" placement="top">
              <el-button type="danger" circle icon="Minus" size="small" @click="handleDeleteEdge" />
            </el-tooltip>
            <el-tooltip content="返回" placement="top">
              <el-button type="info" circle icon="Back" size="small" @click="handleBack" />
            </el-tooltip>
          </div>
        </div>
        <div ref="containerRef" class="container" @dragover="handleDragOver" @drop="handleDrop"></div>
      </el-col>
    </el-row>
    <!-- 数据选择对话框 -->
    <DataSelectDialog
      v-if="showDataDialog"
      v-model="showDataDialog"
      :node-data="currentEditNode"
      :task-info="taskInfo"
      @confirm="handleDataSelectConfirm"
    />
    <!-- 自定义右键菜单 -->
    <div
      v-if="showContextMenu"
      :style="{
        position: 'fixed',
        left: contextMenuX + 'px',
        top: contextMenuY + 'px',
        zIndex: 9999,
      }"
      class="context-menu"
      @click.stop
    >
      <el-card shadow="always" :body-style="{ padding: '8px' }">
        <div class="menu-item" @click="handleMenuSetData(contextMenuNode)"> 📝 设置数据 </div>
        <div class="menu-item" @click="handleMenuEditName(contextMenuNode)"> ✏️ 修改名称 </div>
        <div class="menu-item" @click="handleMenuSetColor(contextMenuNode)"> 🎨 设置颜色 </div>
        <div class="menu-item" @click="handleMenuDeleteNode(contextMenuNode)"> ❌ 删除节点 </div>
      </el-card>
    </div>
  </div>
</template>

<style lang="scss" scoped>
  .app-container {
    height: 100%;
    width: 100%;
    overflow: hidden;
  }

  .main-row {
    height: 100%;
  }

  .panel-col {
    height: 100%;
    // overflow-y: auto;
  }

  .content-col {
    height: 100%;
    display: flex;
    flex-direction: column;
  }

  .topbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 0 10px 0;
    flex-shrink: 0; // 防止压缩
    min-height: 40px; // 固定最小高度

    .tip {
      display: flex;
      align-items: center;
      gap: 16px;
    }
    .toolbar {
      text-align: right;
      margin: 0 30px;
    }
  }
  .container {
    flex: 1; // 占用剩余所有高度
    border: 1px solid #ddd;
    border-radius: 4px;
    min-height: 0; // 允许缩小
  }

  .context-menu {
    .menu-item {
      padding: 8px 12px;
      cursor: pointer;
      border-radius: 4px;
      transition: background-color 0.2s;

      &:hover {
        background-color: #f5f7fa;
      }

      &:not(:last-child) {
        border-bottom: 1px solid #ebeef5;
      }
    }
  }
</style>
